/*
 * 	<pre>
 *	EasyPeas.
 *  Copyright (C) 2007 S Owen
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 * Jul 24, 2007
 * TestAnnotated.java
 * </pre>
 */
package org.easypeas.mappings;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Processes the String representation of a path into its possible constituent parts.
 * <p>
 * For example the path A/B/C could represent:<br>
 * Root:A, {Accessor:B,ID:B}, {Endpoint:C,Accessor:C,ID:C},Endpoint:index
 * </p>
 * The order of each possibilty is the order they should be processed in.
 * @author S Owen
 */
public class Path {
    /**
     * Indicates the type of the element
     */
    public enum PathType {
        /**
         * Represents a method that is annotated as an Accessor
         */
        ACCESSOR, 
        /**
         * Indicates a method that acts as the endpoint and does the final processing. <br>
         * 
         * This will be a View for a GET request, or an Action for a POST or PUT.
         */
        ENDPOINT, 
        /**
         * Represents a special type of default Accessor method, id, which returns another Object
         * related to that ID.<br>
         * For example, in the path users/22/name the element 22 could be a representation of the user ID and returns a User Object upon which the view name is processed.
         */
        ID;
    }
    
    String root;
    List<List<PathElement>> possibleElements = new ArrayList<List<PathElement>>();
    
    /**
     * Creates a new instance of Path and processes the contained elements
     * @param path The String representing the path
     */
    public Path(final String path) {
        process(path);
    }
    
    private void process(String path) {
        //tidy up the path removing any leading or trailing spaces or /
        String refinedPath=path.trim();
        if (refinedPath.startsWith("/")) refinedPath=refinedPath.substring(1);
        if (refinedPath.endsWith("/")) refinedPath=refinedPath.substring(0,refinedPath.length()-1);
        
        if (refinedPath.length()==0) {
            root="index";
            
        }
        else {
            String [] splitPath = refinedPath.split("/");
            root=splitPath[0];
            for (int i=1;i<splitPath.length;i++) {
                List<PathElement> elements = new ArrayList<PathElement>();
                String name = splitPath[i];
                if (i==splitPath.length-1) {
                    elements.add(new PathElement(PathType.ENDPOINT,name));
                    elements.add(new PathElement(PathType.ACCESSOR,name));
                    elements.add(new PathElement(PathType.ID,name));
                }
                else {
                   elements.add(new PathElement(PathType.ACCESSOR,name));
                   elements.add(new PathElement(PathType.ID,name)); 
                }
                
                possibleElements.add(elements);
            } 
        }
        
        //finally add the possibility that the end is the default index endpoint.
        possibleElements.add(Collections.singletonList(new PathElement(PathType.ENDPOINT,"index")));
    }
    
    /**
     * Provides the name of the Root easypea
     * @return the root name
     */
    public String getRoot() {
        return root;
    }
    
    /**
     * Provides a list of the possibiities, in the order they should be processed.
     * @return A List containing a list of the possibilities
     */
    public List<List<PathElement>> getPossibleElements() {
        return possibleElements;
    }
    
    public class PathElement {
        public PathElement(PathType type, String name) {
            this.type=type;
            this.name=name;
        }
        
        public PathType type;
        public String name;
    }
}
